package t1;/*
 * i这个类封装了 码字信息阶段的各个方法
 *   1. 创建码字对象 的数据结构
   2. 创建码字对象 并将该码字对象出现的概率存储到 码字对象中
   3. 计算各个码字的累积概率分布函数 并且存储到 码字对象中
   4. 计算各个码字的 修正概率分布函数 并且存储到码字对象中
   5. 计算各个码字 的编码长度  并且存储到码字对象中

    上面的计算 过程放到另外的方法中 赋值方法独立抽取出来
 * */

import sun.font.CreatedFontTracker;

import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MethodCalculate {

//    计算码字的对象出现的概率

    /**
     * 码字数组 在读取编译文本阶段 创建 并完成赋值
     *
     * @param sum      码字总数  就是码字数组的size
     * @param word_sum 码字出现次数的数组  下标对应 码字数组  在读取编译文本阶段 创建 并完成赋值
     * @return px_array 码字出现的概率 下标对应码字数组
     */
    public ArrayList<Double> CalculatePx(double sum, ArrayList<Integer> word_sum) {
        ArrayList<Double> px_array = new ArrayList<>();
//       计算每个码字 出现的概率 并存入 px_array 中  ，px_array中元素的下标 对应码字的arraylist的下标
        for (Integer num : word_sum) {
            px_array.add(Arith.div(num, sum));
        }

        return px_array;

    }
//    计算该码字的累积分布函数

    /**
     * @param px_array 码字出现概率 的数组 由CalculatePx 方法得到
     * @return 返回码字分布概率的累积函数值
     * 当前元素之前(包括当前元素)所有的px总和 就是fx
     */
    public ArrayList<Double> CalculateFx(ArrayList<Double> px_array) {
        ArrayList<Double> fx_array = new ArrayList<>();
        double sum = 0;
        for (Double px : px_array) {
            sum = Arith.add(sum, px);// 计算从下标为0开始的元素到当前元素的概率总和
            fx_array.add(sum); //将概率分布函数值赋值给 对应的fx
        }
        return fx_array;
    }

    /**
     * 计算 修正的概率分布累积函数值
     *
     * @param px_array 码字出现的概率数组
     * @param fx_array 码字的概率分布累积函数值
     * @return 码字 的 修正的概率分布累积函数值
     * 计算方法 当前元素之前的所有概率分布累积函数值+ (当前码字出现概率值/2)
     */
    public ArrayList<Double> CalculateFabx(ArrayList<Double> px_array, ArrayList<Double> fx_array) {
        Iterator<Double> it_px = px_array.iterator();
        Iterator<Double> it_fx = fx_array.iterator();
        // 获取两个集合的迭代器
//        创建 存储fbax的数组 用来
        ArrayList<Double> fabx_array = new ArrayList<>();

//       第一个fabx的值就是px值的一半        fabx_array.add(String.valueOf(it_px.next()));
//        测试输出 第一个fabx
//        System.out.println("测试输出");
        fabx_array.add(Arith.div(it_px.next(), 2));
//         接下来 从第二个fabx开始 所有的fabx都是 前面一位的fx 加上当前位的 (px/2)
        for (int i = 1; i < px_array.size(); i++) {
            fabx_array.add(Arith.add(it_fx.next(), Arith.div(it_px.next(), 2)));

        }

//        测试  输出fabx 的所有值
        System.out.println("=====fabx_array======");
        System.out.println(fabx_array);
        return fabx_array;

    }

    //   计算 lx的长度 lx向上取整
    public ArrayList<Integer> CalculateLx(ArrayList<Double> px_array) {
        Iterator<Double> it_px = px_array.iterator();
        ArrayList<Integer> lx_array = new ArrayList<>();
        for (int i = 0; i < px_array.size(); i++) {
            lx_array.add((int) Math.ceil((Math.log(1 / it_px.next()) / Math.log(2))) + 1);
        }
//        输出测试
        System.out.println("===lx_array====");
        System.out.println(lx_array);
        return lx_array;
    }

//转换为二进制 比特位
//    需要对fbax的值进行计算与转化
    /*
    转化为 code的过程
    输入 fbax double 输出 一个double
    fbax *2 看看是不是大于1 如果大于1 在取的第一位上取 1 如果小于0 继续乘以2
    如果大于1 那么在取的第二位上取1 并且将1 减去 然后继续进行该转化 过程

    * */
//    转化过程
//void decimal(double m,int code[])
//{
//    int *p = code;
//    if(m>1)
//    {
//        m=m*2;
//
//        *p = (long)m;
//        p++;
//        decimal(m-(long)m,p);
//    }
//}

    /**
     * @param fbax_array 输入概率累积分布函数值的数组
     * @param lx_array   用于控制几次转化循环
     * @return 返回double类型的arraylist 供 CalculateCode进行截取
     */
    public ArrayList<String> Transform(ArrayList<Double> fbax_array, ArrayList<Integer> lx_array) {
        Iterator<Integer> it_lx = lx_array.iterator();
        Iterator<Double> it_fbax = fbax_array.iterator();
        ArrayList<String> trans_array = new ArrayList<>();
//        循环开始 转化为double
        while (it_fbax.hasNext()) {
            Double fbax = it_fbax.next();
            Integer r = it_lx.next();
            StringBuilder str = new StringBuilder("0.");
            for (int i = 0; i < r + 1; i++) {
                if (Arith.mul(fbax, 2) < 1) {  //当前的fbax乘以2 小于1 该位取0
                    str.append("0");
                    fbax = Arith.mul(fbax, 2);
                } else { //当前的fbax乘以2 大于或者等于1 该位取 1 并且 fbax-1 继续循环 直到 lx为止
                    fbax = Arith.mul(fbax, 2);
                    str.append("1");
                    fbax = Arith.sub(fbax, 1);
                }
            }

            trans_array.add(str.toString());

        }
        System.out.println("======trans_array======");
        System.out.println(trans_array);
        return trans_array;


    }


    public ArrayList<String> CalculateCode(ArrayList<Integer> lx_array, ArrayList<String> trans_array) {
//        分别取得两个集合的 迭代器
        Iterator<Integer> it_lx = lx_array.iterator();
        Iterator<String> it_trans = trans_array.iterator();
        ArrayList<String> Code_array = new ArrayList<>();
        while (it_trans.hasNext()) {
            Code_array.add(it_trans.next().substring(2, it_lx.next() + 2));
        }
        System.out.println("=======Code_array========");
        System.out.println(Code_array);
        return Code_array;
    }

    //    创建空白的 SFE_s 直接在 使用时创建
//将该码字的 各种信息 存储到码字对象中
    public void Assignment(ArrayList<SFE_s> sfe_s, ArrayList<Character> word_array, ArrayList<Double> px_array,
                           ArrayList<Double> fx_array, ArrayList<Double> fbax_array,
                           ArrayList<Integer> lx_array, ArrayList<String> code_array,
                           ArrayList<String> trans_array) {
//        获取各个集合的迭代器 iterator
        Iterator<Character> it_word = word_array.iterator();
        Iterator<Double> it_px = px_array.iterator();
        Iterator<Double> it_fx = fx_array.iterator();
        Iterator<Double> it_fbax = fbax_array.iterator();
        Iterator<Integer> it_lx = lx_array.iterator();
        Iterator<String> it_code = code_array.iterator();
        Iterator<String> it_trans = trans_array.iterator();
        while (it_px.hasNext()) {

            sfe_s.add(
                    new SFE_s(it_word.next(), it_px.next(), it_fx.next(),
                            it_fbax.next(), it_lx.next(), it_code.next()
                            , it_trans.next()
                    ));
        }

        System.out.println("======sfe_s=====");
        System.out.println(sfe_s);


    }


}
